<template>
  <section class="pop-map"
    v-show="isShow">
    <div class="box-map">
      <canvas id="map-canvas" :width="width" :height="height"></canvas>
    </div>
    <div class="box-actions">
      <div class="icon-button"
        @click="handleZoom(0.25)">
        <img class="icon" src="@/assets/icon_zoom_in.svg" alt="">
      </div>
      <div class="icon-button"
        @click="handleZoom(-0.25)">
        <img class="icon" src="@/assets/icon_zoom_out.svg" alt="">
      </div>
      <div class="icon-button"
        @click="handleClose()">
        <img class="icon" src="@/assets/icon_close.svg" alt="">
      </div>
    </div>
  </section>
</template>

<script>
import eventBus from '@/EventBus'
import player from '@/models/Player'
import system from '@/models/system'

const MinCanvasSize = 360 // min width and height of canvas
const RoomSize = 20
const RoomGap = 5
const DoorSize = 10
const MinRatio = 1.5
const MaxRatio = 3
const FontSize = 8

export default {
  data () {
    return {
      isShow: false,
      width: MinCanvasSize,
      height: MinCanvasSize,
      ratio: MinRatio,
      canvas: null,
      ctx: null
    }
  },

  mounted () {
    this.canvas = document.querySelector('#map-canvas')
    this.ctx = this.canvas.getContext('2d')

    eventBus.$on('notifyShowMap', () => {
      this.showMap()
    })
  },

  beforeDestroy () {
    eventBus.$off('notifyShowMap')
  },

  methods: {
    showMap () {
      this.isShow = true
      this.drawMap()
    },
    drawMap () {
      const data = [...system.map]
      const coordX = [...new Set(data.map(r => r.x))]
      const coordY = [...new Set(data.map(r => r.y))]
      const startX = Math.min(...coordX)
      const endX = Math.max(...coordX)
      const startY = Math.min(...coordY)
      const endY = Math.max(...coordY)
      const columns = endX - startX + 1
      const rows = endY - startY + 1
      const mapSize = {
        width: columns * (RoomSize + RoomGap) * this.ratio,
        height: rows * (RoomSize + RoomGap) * this.ratio
      }
      let canvasStartX = 0
      let canvasStartY = 0
      if (mapSize.width > MinCanvasSize) {
        this.width = mapSize.width
        canvasStartX = 0
      } else {
        canvasStartX = (MinCanvasSize - mapSize.width) / 2
      }
      if (mapSize.height > MinCanvasSize) {
        this.height = mapSize.height
        canvasStartY = 0
      } else {
        canvasStartY = (MinCanvasSize - mapSize.height) / 2
      }
      // console.log(coordX, coordY)
      // console.log(startX, endX, startY, endY)
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      data.forEach(r => {
        // draw room cell
        this.ctx.fillStyle = 'red'
        this.ctx.fillRect(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio, RoomSize * this.ratio, RoomSize * this.ratio)
        // draw room entrances
        this.ctx.fillStyle = 'white'
        r.doors.forEach(d => {
          const realDoorIndex = (d + r.rotate / 90) % 4
          switch (realDoorIndex) {
            case 0:
              this.ctx.fillRect(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio + (RoomSize - DoorSize) / 2 * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio, DoorSize * this.ratio, 3)
              break
            case 1:
              this.ctx.fillRect(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio + RoomSize * this.ratio - 3, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio + (RoomSize - DoorSize) / 2 * this.ratio, 3, DoorSize * this.ratio)
              break
            case 2:
              this.ctx.fillRect(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio + (RoomSize - DoorSize) / 2 * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio + RoomSize * this.ratio - 3, DoorSize * this.ratio, 3)
              break
            case 3:
              this.ctx.fillRect(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio + (RoomSize - DoorSize) / 2 * this.ratio, 3, DoorSize * this.ratio)
              break
          }
        })
        // draw now location or room name
        if (player.x === r.x && player.y === r.y) {
          this.ctx.fillStyle = 'gold'
          this.ctx.beginPath()
          this.ctx.arc(canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio + RoomSize / 2 * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio + RoomSize / 2 * this.ratio, RoomSize / 4 * this.ratio, 0, 2 * Math.PI)
          this.ctx.fill()
          this.ctx.closePath()
        } else if (['foyer', 'kitchen', 'storage', 'evilTemple', 'garden', 'graveyard'].includes(r.key)) {
          this.ctx.fillStyle = 'white'
          this.ctx.font = `${FontSize * this.ratio}px serif`
          this.ctx.fillText(r.name[0], canvasStartX + (r.x - startX) * (RoomSize + RoomGap) * this.ratio + RoomSize / 4 * this.ratio, canvasStartY + (r.y - startY) * (RoomSize + RoomGap) * this.ratio + RoomSize / 4 * this.ratio + FontSize * this.ratio, RoomSize / 2 * this.ratio)
        }
      })
    },
    handleZoom (ratio) {
      if (this.ratio + ratio <= MaxRatio && this.ratio + ratio >= MinRatio) {
        this.ratio += ratio
        // console.log('ratio now is ', this.ratio)
        this.drawMap()
      }
    },
    handleClose () {
      this.isShow = false
      this.width = MinCanvasSize
      this.height = MinCanvasSize
    }
  }
}
</script>

<style scoped lang="less">
.pop-map {
  position: absolute;
  z-index: 45;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.9);
  .box-map {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 720px;
    height: 720px;
    transform: translate(-50%, -50%);
    border: 4px solid gray;
    overflow: auto;
  }
  .box-actions {
    display: flex;
    justify-content: space-between;
    align-items: end;
    position: fixed;
    z-index: 46;
    left: 0;
    bottom: 0;
    right: 0;
    padding: 24px;
  }
}
</style>
